Microprocessor designers employ many techniques to increase microprocessor performance. Most microprocessors operate using a clock signal running at a fixed frequency. Each clock cycle the circuits of the microprocessor perform their respective functions. According to Hennessy and Patterson (see Computer Architecture: A Quantitative Approach, 3rd Edition), the true measure of a microprocessor's performance is the time required to execute a program or collection of programs. From this perspective, the performance of a microprocessor is a function of its clock frequency, the average number of clock cycles required to execute an instruction (or alternately stated, the average number of instructions executed per clock cycle), and the number of instructions executed in the program or collection of programs. Semiconductor scientists and engineers are continually making it possible for microprocessors to run at faster clock frequencies, chiefly by reducing transistor size, resulting in faster switching times. The number of instructions executed is largely fixed by the task to be performed by the program, although it is also affected by the instruction set architecture of the microprocessor. Large performance increases have been realized by architectural and organizational notions that improve the instructions per clock cycle, in particular by notions of parallelism.
One notion of parallelism that has improved the clock frequency of microprocessors is pipelining, which overlaps execution of multiple instructions within pipeline stages of the microprocessor. In an ideal situation, each clock cycle one instruction moves down the pipeline to a new stage, which performs a different function on the instruction. Thus, although each individual instruction takes multiple clock cycles to complete, the multiple cycles of the individual instructions overlap. Because the circuitry of each individual pipeline stage is only required to perform a small function relative to the sum of the functions required to be performed by a non-pipelined processor, the clock cycle of the pipelined processor may be reduced. The performance improvements of pipelining may be realized to the extent that the instructions in the program permit it, namely to the extent that an instruction does not depend upon its predecessors in order to execute and can therefore execute in parallel with its predecessors, which is commonly referred to as instruction-level parallelism. Another way in which instruction-level parallelism is exploited by contemporary microprocessors is the issuing of multiple instructions for execution per clock cycle. These microprocessors are commonly referred to as superscalar microprocessors.
What has been discussed above pertains to parallelism at the individual instruction-level. However, the performance improvement that may be achieved through exploitation of instruction-level parallelism is limited. Various constraints imposed by limited instruction-level parallelism and other performance-constraining issues have recently renewed an interest in exploiting parallelism at the level of blocks, or sequences, or streams of instructions, commonly referred to as thread-level parallelism. A thread is simply a sequence, or stream, of program instructions. A multithreaded microprocessor concurrently executes multiple threads according to some scheduling policy that dictates the fetching and issuing of instructions of the various threads, such as interleaved, blocked, or simultaneous multithreading. A multithreaded microprocessor typically allows the multiple threads to share the functional units of the microprocessor (e.g., instruction fetch and decode units, caches, branch prediction units, and load/store, integer, floating-point, SIMD, etc. execution units) in a concurrent fashion. However, multithreaded microprocessors include multiple sets of resources, or contexts, for storing the unique state of each thread, such as multiple program counters and general purpose register sets, to facilitate the ability to quickly switch between threads to fetch and issue instructions. In other words, because each thread context has its own program counter and general purpose register set, the multithreading microprocessor does not have to save and restore these resources when switching between threads, thereby potentially reducing the average number of clock cycles per instruction.
One example of a performance-constraining issue addressed by multithreading microprocessors is the fact that accesses to memory outside the microprocessor that must be performed due to a cache miss typically have a relatively long latency. It is common for the memory access time of a contemporary microprocessor-based computer system to be between one and two orders of magnitude greater than the cache hit access time. Instructions dependent upon the data missing in the cache are stalled in the pipeline waiting for the data to come from memory. Consequently, some or all of the pipeline stages of a single-threaded microprocessor may be idle performing no useful work for many clock cycles. Multithreaded microprocessors may solve this problem by issuing instructions from other threads during the memory fetch latency, thereby enabling the pipeline stages to make forward progress performing useful work, somewhat analogously to, but at a finer level of granularity than, an operating system performing a task switch on a page fault. Other examples of performance-constraining issues addressed by multithreading microprocessors are pipeline stalls and their accompanying idle cycles due to a data dependence; or due to a long latency instruction such as a divide instruction, floating-point instruction, or the like; or due to a limited hardware resource conflict. Again, the ability of a multithreaded microprocessor to issue instructions from independent threads to pipeline stages that would otherwise be idle may significantly reduce the time required to execute the program or collection of programs comprising the threads.
Multiprocessing is a technique related to multithreading that exploits thread-level parallelism, albeit at a higher system level, to execute a program or collection of programs faster. In a conventional multiprocessor system, multiple processors, or CPUs, share a memory system and I/O devices. A multiprocessor (MP) operating system facilitates the simultaneous execution of a program or collection of programs on the multiprocessor system. For example, the system may include multiple Pentium IV processors all sharing a memory and I/O subsystem running an MP operating system—such as Linux SMP, an MP-capable version of Windows, Sun Solaris, etc., and executing one or more application programs concurrently.
Multithreading microprocessors exploit thread-level parallelism at an even lower level than multiprocessor systems by sharing instruction fetch, issue, and execution resources, as described above, in addition to sharing a memory system and I/O devices. An MP operating system may run on a multithreading microprocessor if the multithreading microprocessor presents multiple processors, or CPUs, in an architected manner recognized by the MP operating system. Perhaps the most highly publicized example is the Hyper-Threading (HT) Technology employed in the Intel® Xeon® multithreading microprocessor. An HT Xeon includes effectively the same execution resources (e.g., caches, execution units, branch predictors) as a non-HT Xeon processor, but replicates the architectural state to present multiple distinct logical processors to an MP OS. That is, the MP operating system recognizes each logical processor as a separate processor, or CPU, each presenting the architecture of a single processor. The cost of replicating the architectural state for the additional logical processor in the Xeon in terms of additional chip size and power consumption is almost 5%.
One aspect of the architecture presented by each of the multiple processors to the MP operating system is the ability to handle a list of architected exceptions. Generally speaking, an exception is an error or other unusual condition or event that occurs during the execution of a program. In response to an exception, the processor saves the state of the currently executing program and begins fetching and executing instructions at a predetermined address, thereby transferring execution to an alternate program, commonly referred to as an exception handler located at the predefined address. The predefined address may be common to all exceptions in the list of architected exception types or may be unique to some or all of the exception types. The exception handler, when appropriate, may restore the state and resume execution of the previously executing program. Examples of common exceptions include a page fault, a divide by zero, a faulty address generated by the program, a bus error encountered by the processor when attempting to read a memory location, or an invalid instruction exception caused by an invalid instruction opcode or invalid instruction operand.
Another common exception type is an interrupt, or interrupt request. Interrupts are typically grouped as hardware interrupts and software interrupts. A software interrupt is generated when the currently executing program executes an architected software interrupt instruction, which causes an exception that transfers control to the architected interrupt vector associated with the software interrupt to invoke an interrupt service routine, or handler. A hardware interrupt is a signal received by the processor from a device to request service by the processor. Examples of interrupting devices are disk drives, direct memory access controllers, and timers. In response to the interrupt request, the processor transfers control to an architected interrupt vector associated with the interrupt request to invoke an interrupt service routine, or handler.
One function which MP operating systems need to be able to perform is for one processor, or CPU, to interrupt the operation of another specific one of the processors, and in some cases to all the processors in the system. These operations are sometimes referred to as inter-processor interrupts (IPIs). Commonly in a multiprocessor system, each processor includes an interrupt controller, which enables each processor to direct an interrupt specifically to each of the other processors. The HT Xeon processors, for example, include a replicated Advanced Programmable Interrupt Controller (APIC) for each logical processor, which enables each logical processor to send a hardware interrupt specifically to each of the other logical processors.
An example of the use of an IPI is in preemptive time-sharing operating systems, which receive periodic timer interrupts, in response to which the operating system may perform a task switch on one or more of the processors to schedule a different task or process to execute on the processors. In Linux SMP, for example, the timer handling routine running on the processor that receives the timer interrupt not only schedules the tasks on its own processor, but also directs an interrupt to each of the other processors to cause them to schedule their tasks. Each processor has an architected interrupt mechanism, which the timer interrupt-receiving processor uses to direct an IPI to each of the other processors in the multiprocessor system.
Another multithreading microprocessor core architecture which takes a somewhat different approach than, for example, the Intel HT architecture is the MIPS® Multithreading (MT) Application-Specific Extension (ASE) to the MIPS32® Architecture. The MIPS MT ASE allows two distinct, but not mutually-exclusive, multithreading capabilities. A single MIPS MT ASE microprocessor core comprises one or more Virtual Processing Elements (VPEs), and each VPE comprises one or more thread contexts (TCs). This architecture is described in the document MIPS32® Architecture for Programmers Volume IV-f: The MIPS® MT Application-Specific Extension (ASE) to the MIPS32® Architecture, Document Number: MD00378, Revision 1.00, Sep. 28, 2005, available from MIPS Technologies, 1225 Charleston Road, Mountain View, Calif. 94043-1353, which is hereby incorporated by reference in its entirety for all purposes. Embodiments of the architecture are also described in the above-referenced U.S. Patent Applications.
In the MIPS MT ASE architecture, an N-VPE processor core presents to an SMP operating system an N-way symmetric multiprocessor. In particular, it presents to the SMP operating system N MIPS32® Architecture processors. Thus, SMP operating systems configured to run on a conventional multiprocessor system having N MIPS32 processors without the MT ASE capability will run on a single MIPS32 core with the MT ASE capabilities with little or no modifications to the SMP operating system. In particular, each VPE presents an architected exception domain to the SMP operating system including an architected list of exceptions that the VPE will handle. The list includes interrupts that one VPE may direct to another specific VPE in the multithreading microprocessor, somewhat similar to the HT Xeon approach.
As mentioned above, each VPE comprises at least one thread context, and may comprise multiple thread contexts. A thread context in the MIPS MT ASE comprises a program counter representation, a set of general purpose registers, a set of multiplier result registers, and some of the MIPS Privileged Resource Architecture (PRA) Coprocessor 0 state, such as state describing the execution privilege level and address space identifier (ASID) of each thread context. The thread contexts are relatively lightweight compared to VPEs with respect to storage elements required to store state and are therefore less expensive than VPEs in terms of chip area and power consumption. Advantageously, the lightweight feature of MIPS MT ASE thread contexts makes them inherently more scalable than VPEs, and potentially than Intel HT logical processors, for example.
In particular, in the interest of providing lightweight thread contexts and the concomitant advantages, such as improved scalability, within the MIPS MT ASE, the domain for exception handling is at the VPE level, not the thread context level. In particular, a VPE handles asynchronous exceptions, such as interrupts, opportunistically. That is, when an asynchronous exception is raised to the VPE, the VPE selects one of the eligible (i.e., not marked as exempt from servicing asynchronous exceptions) thread contexts to execute the exception handler. Thus, although there is an architected means for a thread context to direct an asynchronous exception to a VPE, the thread context cannot specify to the VPE which thread context should handle the exception within the VPE in a MIPS MT ASE processor, i.e., the exception architecture does not provide an explicit way for the thread context to direct an asynchronous exception to a specific other thread context. This is a problem, particularly with MP operating systems, such as Linux SMP, that rely on the ability of one CPU to direct an inter-processor interrupt to another CPU in response to a timer interrupt request in order to accomplish preemptive multitasked process scheduling.
Therefore, what is needed is a system and method for accomplishing preemptive multitasking by directing an asynchronous timer interrupt request from one thread context to another specific thread context on a multithreading microprocessor in which such an operation is not architecturally supported.